﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;

namespace AvisoSuporte
{
    public partial class ProcessarRelatorioMensal : Form
    {
        private string template = string.Empty;
        private string template_resumo1 = string.Empty;
        private string template_resumo2 = string.Empty;
        private string dataProcessamento = string.Empty;

        private const double Imediato = 8;
        private const double Urgente = 12;
        private const double Alta = 16;
        private const double Normal = 24;
        private const double Baixa = 36;

        public double HorasCorrecaoBug { get; set; }

        public double  HorasCedidasDesenv { get; set; }

        public ProcessarRelatorioMensal()
        {
            InitializeComponent();
        }

        private void ProcessarRelatorio_Load(object sender, EventArgs e)
        {
            this.HorasCorrecaoBug = 0;

            this.cmbColaboradores.SelectedItem = "4";
            this.cmbHorasTrabalhadas.SelectedItem = "8";
            this.cmbMes.SelectedIndex = DateTime.Now.Month - 1;

            for (int i = DateTime.Now.Year - 10; i < DateTime.Now.Year + 10; i++)
            {
                this.cmbAno.Items.Add(i);
            }

            this.cmbAno.SelectedItem = DateTime.Now.Year;
        }

        private void ProcessMonthlyReport()
        {
            dataProcessamento = this.cmbMes.SelectedItem + " - " + this.cmbAno.SelectedItem;

            template_resumo1 = @"<tr>
                                    <td>Carga Máxima de Trabalho</td>
                                    <td style='color: Black; text-align:right'>{0}</td>
                                    <td>Horas</td>
                                    <td>Coordenador</td>
                                    <td style='color: Black; text-align:right'>{1}</td>                                    
                                </tr>
                                <tr>
                                    <td>Horas de Correção de Bug</td>
                                    <td style='color: Black; text-align:right'>{2}</td>
                                    <td>Horas</td>
                                    <td>Team System</td>
                                    <td style='color: Black; text-align:right'>{3}</td>                                    
                                </tr>
                                <tr>
                                    <td>Horas Cedidas para o  Desenvolvimento</td>
                                    <td style='color: Black; text-align:right'>{4}</td>
                                    <td>Horas</td>
                                    <td>EPM</td>
                                    <td style='color: Black; text-align:right'>{5}</td>                                    
                                </tr>
                                <tr>
                                    <td>Desvio de esforço produtivo</td>
                                    <td style='color: Black; text-align:right'>{6}</td>
                                    <td>Horas</td>
                                    <td>Site Suporte 3º Nível</td>
                                    <td style='color: Black; text-align:right'>{7}</td>                                    
                                </tr>
                                <tr>
                                    <td>Índice de Disponibilidade</td>
                                    <td style='color: Black; text-align:right'>{8}</td>
                                    <td>Horas</td>
                                    <td>EPM/Team System</td>
                                    <td style='color: Black; text-align:right'>{9}</td>                                    
                                </tr>";

            template_resumo2 = @"<tr>
                                    <td>Chamados Totais no Período</td>
                                    <td style='color: Black; text-align:right'>{0}</td>
                                    <td>Work Items</td>
                                    <td>Team System</td>
                                    <td style='color: Black; text-align:right'>{1}</td>                                    
                                </tr>
                                <tr>
                                    <td>Chamados em Aberto</td>
                                    <td style='color: Black; text-align:right'>{2}</td>
                                    <td>Work Items</td>
                                    <td>Team System</td>
                                    <td style='color: Black; text-align:right'>{3}</td>                                    
                                </tr>
                                <tr>
                                    <td>Chamados em Aberto fora da SLA</td>
                                    <td style='color: Black; text-align:right'>{4}</td>
                                    <td>Work Items</td>
                                    <td>Team System</td>
                                    <td style='color: Black; text-align:right'>{5}</td>                                    
                                </tr>
                                <tr>
                                    <td>Chamados Resolvidos</td>
                                    <td style='color: Black; text-align:right'>{6}</td>
                                    <td>Work Items</td>
                                    <td>Team System</td>
                                    <td style='color: Black; text-align:right'>{7}</td>                                    
                                </tr>
                                <tr>
                                    <td>Chamados Resolvidos fora da SLA</td>
                                    <td style='color: Black; text-align:right'>{8}</td>
                                    <td>Work Items</td>
                                    <td>Team System</td>
                                    <td style='color: Black; text-align:right'>{9}</td>                                    
                                </tr>
                                <tr>
                                    <td>Chamados Reabertos</td>
                                    <td style='color: Black; text-align:right'>{10}</td>
                                    <td>Work Items</td>
                                    <td>Team System</td>
                                    <td style='color: Black; text-align:right'>{11}</td>                                    
                                </tr>
                                <tr>
                                    <td>Divergência entre o Remedy e Team System</td>
                                    <td style='color: Black; text-align:right'>{12}</td>
                                    <td>Work Items</td>
                                    <td>Team System/Remedy</td>
                                    <td style='color: Black; text-align:right'>{13}</td>                                    
                                </tr>";

            template = System.IO.File.ReadAllText(@"Template\mensal.html", Encoding.Default);

            template = template.Replace("<data></data>", dataProcessamento);
            this.GeraResumo(template_resumo1, template_resumo2);
            template = template.Replace("<observacoes></observacoes>", txtObservacoes.Text.Replace("\r\n", "<br/>"));

            if (!System.IO.Directory.Exists(txtCaminho.Text))
            {
                System.IO.Directory.CreateDirectory(txtCaminho.Text);
            }

            string fileName = String.Empty;
            fileName = txtCaminho.Text + "/relatoriosuporte_" + new DateTime((int)this.cmbAno.SelectedItem, (int)this.cmbMes.SelectedIndex + 1, 1).ToString("MMMMyyyy") + ".html";
            System.IO.File.WriteAllText(fileName, template, Encoding.Default);

            DialogResult resultado = MessageBox.Show(this, "Processanto efetuado. Deseja enviar e-mail com o Resumo do dia?", "Processamento Finalizado", MessageBoxButtons.YesNo);

            if (resultado == DialogResult.Yes)
            {
                //enviar email
                Microsoft.Office.Interop.Outlook.Application oApp = new Microsoft.Office.Interop.Outlook.Application();
                Microsoft.Office.Interop.Outlook.MailItem oMsg = (Microsoft.Office.Interop.Outlook.MailItem)oApp.CreateItem(Microsoft.Office.Interop.Outlook.OlItemType.olMailItem);

                string titulo = string.Empty;
                string corpo = string.Empty;
                string to = string.Empty;
                string email_to = string.Empty;
                string corpo_release = string.Empty;
                string to_release = string.Empty;

                titulo = "Relatório do Mês - " + dataProcessamento;
                corpo += "Anexo Relatório do mês para análise." + Environment.NewLine + Environment.NewLine;
                corpo += "Equipe Suporte CDSB" + Environment.NewLine;

                to = "p-jpontes@bvmf.com.br;p-mprudente@bvmf.com.br;p-cagoncalves@bvmf.com.br";

                oMsg.Subject = titulo;
                oMsg.To = to;
                oMsg.Body = corpo;
                oMsg.Importance = Microsoft.Office.Interop.Outlook.OlImportance.olImportanceNormal;
                oMsg.Attachments.Add(fileName, Microsoft.Office.Interop.Outlook.OlAttachmentType.olByValue, 1, "");
                ((Microsoft.Office.Interop.Outlook._MailItem)oMsg).Send();
            }
        }

        private void GeraResumo(string template_resumo1, string template_resumo2)
        {
            int bugsAbertos = 0;
            int bugsAbertosForaSLA = 0;
            int bugsResolvidos = 0;
            int bugsResolvidosForaSLA = 0;
            int bugsReabertos = 0;

            this.HorasCorrecaoBug = 0;

            //pega os dados dos bugs do dia
            DateTime dataInicio = new DateTime((int)this.cmbAno.SelectedItem, (int)this.cmbMes.SelectedIndex + 1, 1);
            DateTime dataFim = dataInicio.AddMonths(1);
            dataFim = dataFim.AddDays(-1);
            List<Model.WorkItem> bugs = new AvisoSuporte.Communication.Geral().RetornaBugsMes(dataInicio, dataFim);

            foreach (Model.WorkItem item in bugs)
            {
                if (!item.State.Equals("Cancelado"))
                {
                    if (item.NaoCorrigido)
                    {
                        bugsReabertos++;
                    }
                    else if (item.State.Equals("Ativo") || item.State.Equals("Analise") || item.State.Equals("Codificacao") || item.State.Equals("Codificado"))
                    {
                        if ((item.AssignedTo.Equals("Carlos Alberto Gonçalves Carvalho")) ||
                            (item.AssignedTo.Equals("Joao Paulo Gregório Pontes")) ||
                            (item.AssignedTo.Equals("Marcelo Luis Prudente do Amaral")))
                        
                        {
                            switch (item.Rank)
                            {
                                case "Imediato":
                                    if (item.HoursPlanned > Imediato)
                                    {
                                        bugsAbertosForaSLA++;
                                    }
                                    break;
                                case "Urgente":
                                    if (item.HoursPlanned > Urgente)
                                    {
                                        bugsAbertosForaSLA++;
                                    }
                                    break;
                                case "Alta":
                                    if (item.HoursPlanned > Alta)
                                    {
                                        bugsAbertosForaSLA++;
                                    }
                                    break;
                                case "Normal":
                                    if (item.HoursPlanned > Normal)
                                    {
                                        bugsAbertosForaSLA++;
                                    }
                                    break;
                                case "Baixa":
                                    if (item.HoursPlanned > Baixa)
                                    {
                                        bugsAbertosForaSLA++;
                                    }
                                    break;
                            }

                            bugsAbertos++;
                        }
                    }
                    else
                    {
                        switch (item.Rank)
                        {
                            case "Imediato":
                                if (item.HoursRealized > Imediato)
                                {
                                    bugsResolvidosForaSLA++;
                                }
                                break;
                            case "Urgente":
                                if (item.HoursRealized > Urgente)
                                {
                                    bugsResolvidosForaSLA++;
                                }
                                break;
                            case "Alta":
                                if (item.HoursRealized > Alta)
                                {
                                    bugsResolvidosForaSLA++;
                                }
                                break;
                            case "Normal":
                                if (item.HoursRealized > Normal)
                                {
                                    bugsResolvidosForaSLA++;
                                }
                                break;
                            case "Baixa":
                                if (item.HoursRealized > Baixa)
                                {
                                    bugsResolvidosForaSLA++;
                                }
                                break;
                        }

                        bugsResolvidos++;
                    }
                    this.HorasCorrecaoBug = this.HorasCorrecaoBug + item.HoursRealized;
                }
            }

            int divergencia = 0;// DivergenciaRemedyXTeamSystem();
            this.HorasCorrecaoBug = this.HorasCorrecaoBug + (2 * (8 * this.DiasUteis()));
            this.HorasCedidasDesenvolvimento();
            double indiceDisponibilidade = this.IndiceDisponibilidade();

            double dep = 0;
            Double.TryParse((String.IsNullOrEmpty(this.txtDEP.Text) ? "0" : this.txtDEP.Text.Replace(".", ",")), out dep);

            template = template.Replace("<resumo_produto1></resumo_produto1>", string.Format(template_resumo1, this.CargaMaximaTrabalho(), "100%", this.HorasCorrecaoBug, this.Map3(this.HorasCorrecaoBug, this.CargaMaximaTrabalho()), this.HorasCedidasDesenv, this.Map3(this.HorasCedidasDesenv, this.CargaMaximaTrabalho()), dep, this.Map3(dep, this.CargaMaximaTrabalho()), indiceDisponibilidade, this.Map3(indiceDisponibilidade, this.CargaMaximaTrabalho())));
            template = template.Replace("<resumo_produto2></resumo_produto2>", string.Format(template_resumo2, bugs.Count(), "100%", bugsAbertos, this.Map3(Convert.ToDouble(bugsAbertos), Convert.ToDouble(bugs.Count())), bugsAbertosForaSLA, this.Map3(Convert.ToDouble(bugsAbertosForaSLA), Convert.ToDouble(bugs.Count())), bugsResolvidos, this.Map3(Convert.ToDouble(bugsResolvidos), Convert.ToDouble(bugs.Count())), bugsResolvidosForaSLA, this.Map3(Convert.ToDouble(bugsResolvidosForaSLA), Convert.ToDouble(bugs.Count())), bugsReabertos, this.Map3(Convert.ToDouble(bugsReabertos), Convert.ToDouble(bugs.Count())), divergencia, this.Map3(Convert.ToDouble(divergencia), Convert.ToDouble(bugs.Count()))));
        }

        private double IndiceDisponibilidade()
        {
            double hcb = this.HorasCorrecaoBug;
            double hcd = this.HorasCedidasDesenv;
            int cmt = this.CargaMaximaTrabalho();

            return (cmt - (hcb + hcd));
        }

        private void HorasCedidasDesenvolvimento()
        {
            this.HorasCedidasDesenv = 0;
            //pega os dados dos bugs do dia
            DateTime dataInicio = new DateTime((int)this.cmbAno.SelectedItem, (int)this.cmbMes.SelectedIndex + 1, 1);
            DateTime dataFim = dataInicio.AddMonths(1);
            dataFim = dataFim.AddDays(-1);
            List<Model.WorkItem> task = new AvisoSuporte.Communication.Geral().RetornaTaskDesenvMes(dataInicio, dataFim);

            foreach (Model.WorkItem item in task)
            {
                if (!String.IsNullOrEmpty(item.CorrigidoPor))
                {
                    if (item.CorrigidoPor.Equals("Carlos Alberto Gonçalves Carvalho")    || 
                        item.CorrigidoPor.Equals("Joao Paulo Gregório Pontes")     ||
                        item.CorrigidoPor.Equals("Marcelo Luis Prudente do Amaral"))

                    {
                        if (!String.IsNullOrEmpty(item.State) && (item.State.Equals("Concluida")))
                        {
                            this.HorasCedidasDesenv = this.HorasCedidasDesenv + item.HoursRealized;
                        }
                        else if (!String.IsNullOrEmpty(item.State) && (item.State.Equals("Em Codificacao") || item.State.Equals("Em Teste")))
                        {
                            
                        }
                    }                    
                }
            }
        }

        private int DivergenciaRemedyXTeamSystem()
        {
            List<int> numerosIncidentes = new List<int>();
            List<Model.GridRemedy> listaRemedy = new List<Model.GridRemedy>();
            int divergencia = 0;

            Remedy remedy = new Remedy();
            AvisoSuporte.remedyWS.GetListOutputMapGetListValues[] listaRemedyGet = remedy.getIncidentsWS(@" ('Assigned Group' = ""DO-CDSB-SUPORTE-CODIFICACAO"" or 'Assigned Group' = ""DO-DSE-SUPORTE NIVEL 3"")");
            
            foreach (AvisoSuporte.remedyWS.GetListOutputMapGetListValues item in listaRemedyGet)
            {
                if (item.Status != AvisoSuporte.remedyWS.StatusType.Closed
                    && item.Status != AvisoSuporte.remedyWS.StatusType.Cancelled
                    && item.Status != AvisoSuporte.remedyWS.StatusType.Resolved)
                {
                    //verifica os workitens do tfs
                    numerosIncidentes.Add(this.ExtraiNumero(item.Incident_Number));
                }
            }

            Communication.Geral geral = new AvisoSuporte.Communication.Geral();
            List<Model.WorkItem> workItens = geral.RetornaWorkItensPorRemedy(numerosIncidentes);

            foreach (AvisoSuporte.remedyWS.GetListOutputMapGetListValues item in listaRemedyGet)
            {
                if (item.Status != AvisoSuporte.remedyWS.StatusType.Closed
                    && item.Status != AvisoSuporte.remedyWS.StatusType.Cancelled
                    && item.Status != AvisoSuporte.remedyWS.StatusType.Resolved)
                {
                    Model.GridRemedy linha = new Model.GridRemedy();
                    linha.Id = this.ExtraiNumero(item.Incident_Number);
                    linha.Titulo = item.Description;
                    linha.ListaWorkItens = RetornaLista(workItens, linha.Id);
                    listaRemedy.Add(linha);
                }

            }

            foreach (Model.GridRemedy item in listaRemedy)
            {
                if (item.ListaWorkItens.Count == 0)
                {
                    divergencia++;
                }

            }

            return divergencia;
        }

        private int ExtraiNumero(string incidente)
        {
            return Convert.ToInt32(incidente.Replace("INC", ""));
        }

        private List<Model.GridWorkItems> RetornaLista(List<AvisoSuporte.Model.WorkItem> workItens, int numeroIncidente)
        {
            List<Model.GridWorkItems> retorno = new List<Model.GridWorkItems>();
            foreach (Model.WorkItem item in workItens)
            {
                if (item.Remedy != string.Empty)
                    if (Convert.ToInt32(item.Remedy) == numeroIncidente)
                        retorno.Add(new Model.GridWorkItems() { Id = item.ID, DataFinal = item.FinishDate, DataInicial = item.StartDate, Status = item.State, Titulo = item.Title, Tipo = item.WorkItemType, CreatedBy = item.CreatedBy });

            }
            return retorno;
        }

        private string Map3(Double value, Double max)
        {
            Double percentual = value * 100 / max;

            return String.Format("{0:0.00}", percentual) + "%";
        }

        private int CargaMaximaTrabalho()
        {
            int x = 0; // Número de Colaboradores 
            int y = this.DiasUteis();
            int z = 0; // Número de horas que deveria ser trabalhada por colaborador
            int d = 0; // Descanso Anual em horas

            Int32.TryParse(this.cmbColaboradores.SelectedItem.ToString(), out x);
            Int32.TryParse(this.cmbHorasTrabalhadas.SelectedItem.ToString(), out z);
            Int32.TryParse(this.txtDescansoAnual.Text, out d);
            
            return (x * y * z) - d * 8;
        }

        private int DiasUteis()
        {
            int year = (int)this.cmbAno.SelectedItem;
            int month = (int)this.cmbMes.SelectedIndex + 1;
            int y = 0; // Número de dias úteis trabalhados

            DateTime date = new DateTime(year, month, 1);

            for (int i = 1; i <= DateTime.DaysInMonth(year, month); i++)
            {
                //Conta apenas dias da semana.
                if (date.DayOfWeek != DayOfWeek.Sunday && date.DayOfWeek != DayOfWeek.Saturday)
                {
                    if (!this.VerificaSeFeriado(date))
                    {
                        y++;
                    }
                }

                date = date.AddDays(1);
            }

            return y;
        }

        private DateTime CalculaPascoa(int ano)
        {
            int a;
            int b;
            int c;
            int d;
            int e;
            int f;
            int g;
            int h;
            int i;
            int j;
            int k;
            int l;
            int m;
            int n;
            int p;
            int q;
            int r;
            int s;

            a = ano / 100;      // o inteiro de (Ano ÷ 100)
            b = ano % 19;       // o resto de (Ano ÷ 19)
            c = (a - 17) / 25;  // o inteiro de [(A - 17) ÷ 25]
            d = a / 4;          // o inteiro de (a ÷ 4)
            e = (a - c) / 3;    // o inteiro de [(a - c) ÷ 3]
            f = (a - d - e + (19 * b) + 15) % 30;    // o resto de {[a - d - E + (19xB) + 15] ÷ 30}
            g = f / 28;         // o inteiro de (F ÷ 28)
            h = 29 / (f + 1);   // o inteiro de [29 ÷ (F + 1)]
            i = (21 - b) / 11;  // o inteiro de [(21 - B) ÷ 11]
            j = g * h * i;
            k = f - (g * (1 - j));
            l = ano / 4;        // o inteiro de (ano ÷ 4)
            m = (ano + l + k + 2 - a + d) % 7;  // o resto de [(ano + L + K + 2 - a + d) ÷ 7]
            n = k - m;
            p = (n + 40) / 44;  // o inteiro de [(N + 40) ÷ 44]
            q = 3 + p;
            r = q / 4;          // o inteiro de (Q ÷ 4)
            s = n + 28 - (31 * r);

            return new DateTime(ano, q, s);
        }

        private bool VerificaSeFeriado(DateTime data)
        { 
            List<DateTime> feriados = new List<DateTime>();
            int ano;
            DateTime pascoa;
            bool feriado = false;

            ano = data.Year;
            pascoa = this.CalculaPascoa(ano);

            feriados.Add(new DateTime(ano, 01, 01));   // Confraternização Universal
            feriados.Add(new DateTime(ano, 04, 21));   // Tiradentes
            feriados.Add(new DateTime(ano, 05, 01));   // Trabalho
            feriados.Add(new DateTime(ano, 08, 07));   // Independência do Brasil
            feriados.Add(new DateTime(ano, 10, 12));   // Nossa Senhora Aparecida
            feriados.Add(new DateTime(ano, 11, 02));   // Finados
            feriados.Add(new DateTime(ano, 11, 15));   // Proclamação da Repúplica
            feriados.Add(new DateTime(ano, 12, 25));   // Natal

            feriados.Add(pascoa.AddDays(-2));          // Sexta Paixão
            feriados.Add(pascoa.AddDays(-47));         // Carnaval
            feriados.Add(pascoa.AddDays(60));          // Corpus Christi

            foreach (DateTime item in feriados)
            {
                if (item.CompareTo(data) == 0)
                {
                    feriado = true;
                }
            }

            return feriado;
        }

        private void btnBuscar_Click(object sender, EventArgs e)
        {
            folderBrowserDialog.ShowDialog(this);
            txtCaminho.Text = folderBrowserDialog.SelectedPath;
        }

        private void btnProcessar_Click(object sender, EventArgs e)
        {
            this.ProcessMonthlyReport();
        }
    }
}
